package org.graduation.recruitment.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.time.DateUtils;
import org.graduation.recruitment.entity.pojo.User;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
@Slf4j
public class Token {
    // 使用HMAC256算法的密钥
    private final Algorithm algorithm = Algorithm.HMAC256("45127jksh");

    /**
     * 生成Token
     *
     * @param user 用户信息
     * @return 生成的Token字符串
     */
    public String generateToken(User user) {
        String token = null;
        try {
            token = JWT.create()
                    .withIssuer("my_graduation_project")    // 设置发行者
                    .withIssuedAt(new Date())   // 设置签发时间
                    .withExpiresAt(DateUtils.addDays(new Date(), 15))   // 设置过期时间
                    .withClaim("id", user.getId()) // 添加用户ID到Token中
                    .withClaim("userType", user.getUserType()) // 添加用户类型到Token中
                    .sign(algorithm);
            System.out.println(token);
        } catch (JWTCreationException e) {
            // 处理Token创建异常
            e.printStackTrace();
        }
        return token;
    }

    /**
     * 验证Token
     *
     * @param token 待验证的Token字符串
     * @return 验证通过返回true，否则返回false
     */
    public boolean verifyToken(String token) {
        try {
            token = subBearerByTokenStr(token);
            JWTVerifier verifier = JWT.require(algorithm)
                    .withIssuer("my_graduation_project") // 匹配指定的token发布者
                    .build();
            verifier.verify(token); // 解码JWT进行验证
            return true;
        } catch (JWTVerificationException e) {
            // 处理Token验证异常
            log.info("token验证失败:" + e);
            return false;
        }
    }

    /**
     * 从请求中获取用户ID
     *
     * @param request HTTP请求对象
     * @return 用户ID
     */
    public Long getUidByRequest(HttpServletRequest request) {
        return getUidByToken(getTokenByRequest(request));
    }

    /**
     * 从Token中获取指定的claim
     *
     * @param token Token字符串
     * @param claim claim名称
     * @return claim的值
     */
    public Object getClaim(String token, String claim) {
        try {
            token = subBearerByTokenStr(token);
            JWTVerifier verifier = JWT.require(algorithm)
                    .withIssuer("my_graduation_project") // 匹配指定的token发布者
                    .build();
            DecodedJWT jwt = verifier.verify(token);
            return jwt.getClaim(claim);
        } catch (Exception e) {
            // 处理获取claim异常
            log.warn("获取token载荷失败\ntoken:" + token + "\nclaim:" + claim);
            return null;
        }
    }

    /**
     * 从HTTP请求中获取Token
     *
     * @param request HTTP请求对象
     * @return 获取到的Token字符串
     */
    public String getTokenByRequest(HttpServletRequest request) {
        String tokenStr = request.getHeader("Authorization");
        if (tokenStr == null) {
            tokenStr = request.getHeader("authorization");
        }
        tokenStr = subBearerByTokenStr(tokenStr);
        return tokenStr;
    }

    /**
     * 通过Token获取用户ID
     *
     * @param token Token字符串
     * @return 用户ID
     */
    public Long getUidByToken(String token) {
        try {
            token = subBearerByTokenStr(token);
            JWTVerifier verifier = JWT.require(algorithm)
                    .withIssuer("my_graduation_project") // 匹配指定的token发布者
                    .build();
            DecodedJWT jwt = verifier.verify(token);
            return Long.parseLong(String.valueOf(jwt.getClaim("id")));
        } catch (Exception e) {
            // 处理解析Token异常
            e.printStackTrace();
            return -1L;
        }
    }

    /**
     * 从Token字符串中移除前缀"Bearer "
     *
     * @param tokenStr Token字符串
     * @return 移除前缀后的Token字符串
     */
    protected String subBearerByTokenStr(String tokenStr) {
        if (tokenStr != null && tokenStr.startsWith("Bearer ")) {
            tokenStr = tokenStr.substring(7);
        }
        return tokenStr;
    }
}